﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace TestByWire
{
    public class LambdaExpressionComparer : IComparer<LambdaExpression>, IComparer
    {
        public int Compare(LambdaExpression x, LambdaExpression y)
        {
            if (x.Parameters.Count != y.Parameters.Count)
                return 1;

            for (int i = 0; i < x.Parameters.Count; i++)
            {
                if (x.Parameters[i].Type != y.Parameters[i].Type)
                    return 1;
            }

            var xBody = ((MethodCallExpression)x.Body);
            var yBody = ((MethodCallExpression)y.Body);

            if (xBody.Method.Name != yBody.Method.Name)
                return 1;

            var col1 = xBody.Arguments;
            var col2 = yBody.Arguments;

            if (col1.Count != col2.Count)
                return 1;

            for (int i = 0; i < col1.Count; i++)
            {
                var arg1 = col1[i] as ConstantExpression;
                var arg2 = col2[i] as ConstantExpression;

                Type typeOne = null;
                Type typeTwo = null;

				if (arg1 != null && arg2 != null)
				{
					typeOne = arg1.Type;
					typeTwo = arg2.Type;
				}
				else
				{
					var fieldArg1 = col1[i] as MemberExpression;
					var fieldArg2 = col2[i] as MemberExpression;

					if (fieldArg1 != null && fieldArg2 != null)
					{
						typeOne = fieldArg1.Type;
						typeTwo = fieldArg2.Type;
					}
				}

				if (!Equals(typeOne, typeTwo))
                    return 1;

            }
            return 0;
        }

        public int Compare(object x, object y)
        {
            if (x == null && y == null)
                return 0;
            if (x == null)
                return 1;
            if (y == null)
                return -1;

            if (x is LambdaExpression && y is LambdaExpression)
                return Compare(x, y);

            return x.GetType().FullName.CompareTo(y.GetType().FullName);
        }
    }
}